package org.wu.framework.authorization.platform.application.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.wu.framework.authorization.model.UserDetails;
import org.wu.framework.authorization.platform.application.SysUserApplication;
import org.wu.framework.authorization.platform.application.assembler.SysUserDTOAssembler;
import org.wu.framework.authorization.platform.application.command.CreateSysZoneInitCommand;
import org.wu.framework.authorization.platform.application.command.SysUserCommand;
import org.wu.framework.authorization.platform.application.dto.SysPermissionDTO;
import org.wu.framework.authorization.platform.domain.model.sys.menu.SysMenu;
import org.wu.framework.authorization.platform.domain.model.sys.permission.SysPermission;
import org.wu.framework.authorization.platform.domain.model.sys.permission.SysPermissionRepository;
import org.wu.framework.authorization.platform.domain.model.sys.role.SysRole;
import org.wu.framework.authorization.platform.domain.model.sys.role.SysRoleRepository;
import org.wu.framework.authorization.platform.domain.model.sys.role.menu.SysRoleMenuRepository;
import org.wu.framework.authorization.platform.domain.model.sys.role.permission.SysRolePermission;
import org.wu.framework.authorization.platform.domain.model.sys.role.permission.SysRolePermissionRepository;
import org.wu.framework.authorization.platform.domain.model.sys.user.SysUser;
import org.wu.framework.authorization.platform.domain.model.sys.user.SysUserRepository;
import org.wu.framework.authorization.platform.domain.model.sys.user.role.SysUserRole;
import org.wu.framework.authorization.platform.domain.model.sys.user.role.SysUserRoleRepository;
import org.wu.framework.authorization.platform.domain.model.sys.zone.SysZone;
import org.wu.framework.authorization.platform.domain.model.sys.zone.SysZoneRepository;
import org.wu.framework.authorization.platform.domain.model.sys.zone.user.SysZoneUser;
import org.wu.framework.authorization.platform.domain.model.sys.zone.user.SysZoneUserRepository;
import org.wu.framework.core.NormalUsedString;
import org.wu.framework.core.utils.ObjectUtils;
import org.wu.framework.lazy.orm.core.persistence.reverse.lazy.ddd.DefaultDDDLazyApplicationImpl;
import org.wu.framework.lazy.orm.database.lambda.domain.LazyPage;
import org.wu.framework.lazy.orm.web.plus.stereotype.LazyApplication;
import org.wu.framework.web.response.Result;
import org.wu.framework.web.response.ResultFactory;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * describe
 *
 * @author Jia wei Wu
 * @date 2023/05/17 11:19 晚上
 * @see DefaultDDDLazyApplicationImpl
 **/
@LazyApplication
public class SysUserApplicationImpl implements SysUserApplication {

    @Autowired
    SysUserRepository sysUserRepository;

    @Autowired
    SysUserRoleRepository sysUserRoleRepository;

    @Autowired
    SysRoleMenuRepository sysRoleMenuRepository;

    @Autowired
    SysZoneRepository sysZoneRepository;

    @Autowired
    SysZoneUserRepository sysZoneUserRepository;

    @Autowired
    SysPermissionRepository sysPermissionRepository;

    @Autowired
    SysRoleRepository sysRoleRepository;

    @Autowired
    SysRolePermissionRepository sysRolePermissionRepository;


    /**
     * describe 新增
     *
     * @param
     * @return
     * @exception/throws
     * @author Jia wei Wu
     * @date 2023/05/17 11:19 晚上
     **/

    @Override
    public Result<SysUser> save(SysUserCommand sysUserCommand) {
        SysUser sysUser = SysUserDTOAssembler.toSysUser(sysUserCommand);
        // 保存用户
        Result<SysUser> story = sysUserRepository.story(sysUser);
        // 存储用户角色
        if (story.isSuccess()) {
            SysUser data = story.getData();
            Long userId = data.getId();
            List<SysUserRole> sysUserRoleList = sysUserCommand.getRoleIds().stream().map(roleId -> {
                SysUserRole sysUserRole = new SysUserRole();
                sysUserRole.setUserId(userId);
                sysUserRole.setRoleId(roleId);
                sysUserRole.setIsDeleted(false);
                return sysUserRole;
            }).collect(Collectors.toList());
            sysUserRoleRepository.batchStoryUserRole(userId, sysUserRoleList);
        }
        return story;
    }

    /**
     * describe 更新
     *
     * @param
     * @return
     * @exception/throws
     * @author Jia wei Wu
     * @date 2023/05/17 11:19 晚上
     **/

    @Override
    public Result<SysUser> update(SysUserCommand sysUserCommand) {
        return save(sysUserCommand);
    }

    /**
     * describe 查询单个
     *
     * @param
     * @return
     * @exception/throws
     * @author Jia wei Wu
     * @date 2023/05/17 11:19 晚上
     **/

    @Override
    public Result<SysUser> findOne(SysUserCommand sysUserCommand) {
        SysUser sysUser = SysUserDTOAssembler.toSysUser(sysUserCommand);
        return sysUserRepository.findOne(sysUser);
    }

    /**
     * describe 查询多个
     *
     * @param
     * @return
     * @exception/throws
     * @author Jia wei Wu
     * @date 2023/05/17 11:19 晚上
     **/

    @Override
    public Result<List<SysUser>> findList(SysUserCommand sysUserCommand) {
        SysUser sysUser = SysUserDTOAssembler.toSysUser(sysUserCommand);
        Result<List<SysUser>> sysUserRepositoryList = sysUserRepository.findList(sysUser);

        // 获取用户角色
        return sysUserRepositoryList;
    }

    /**
     * describe 分页查询多个
     *
     * @param
     * @return
     * @exception/throws
     * @author Jia wei Wu
     * @date 2023/05/21 11:16 晚上
     **/

    @Override
    public Result<LazyPage<SysUser>> findPage(int size, int current, SysUserCommand sysUserCommand) {
        SysUser sysUser = SysUserDTOAssembler.toSysUser(sysUserCommand);
        return sysUserRepository.findPage(size, current, sysUser);
    }

    /**
     * describe 删除
     *
     * @param
     * @return
     * @exception/throws
     * @author Jia wei Wu
     * @date 2023/05/17 11:19 晚上
     **/

    @Override
    public Result<SysUser> delete(SysUserCommand sysUserCommand) {
        SysUser sysUser = SysUserDTOAssembler.toSysUser(sysUserCommand);
        return sysUserRepository.delete(sysUser);
    }

    /**
     * 查询用户菜单
     *
     * @param module      用户模块
     * @param userDetails 用户信息
     * @return Result<List < SysMenu>>
     */
    @Override
    public Result<List<SysMenu>> findUserMenuList(String module, UserDetails userDetails) {
        Long userId = userDetails.getId();
        // 查询用户角色
        SysUserRole sysUserRole = new SysUserRole();
        sysUserRole.setUserId(userId);
        Result<List<SysUserRole>> userRoleRepositoryList = sysUserRoleRepository.findList(sysUserRole);
        if (userRoleRepositoryList.isSuccess()) {
            // 查询角色菜单
            List<Long> roleIds = userRoleRepositoryList.getData().stream().map(SysUserRole::getRoleId).toList();
            if (!ObjectUtils.isEmpty(roleIds)) {
                return sysRoleMenuRepository.findRoleMenuList(module, roleIds);
            } else {
                return ResultFactory.successOf(new ArrayList<>());
            }
        } else {
            return ResultFactory.errorOf("无法查询到用户角色" + userRoleRepositoryList.getMessage());
        }

    }

    /**
     * 获取用户区域
     *
     * @param userId 用户ID
     * @return
     */
    @Override
    public Result<List<SysZone>> findUseZoneList(Long userId) {
        return sysUserRepository.findUseZoneList(userId);
    }

    /**
     * 新增用户区域
     *
     * @param userDetails
     * @param createSysZoneInitCommand
     * @return
     */
    @Override
    public Result<?> createAndInitZone(UserDetails userDetails, CreateSysZoneInitCommand createSysZoneInitCommand) {
        // 新增区域
        SysZone sysZone = new SysZone();
        String zoneCode = UUID.randomUUID().toString();
        sysZone.setCode(zoneCode);
        sysZone.setIsDeleted(false);
        sysZone.setCreateTime(LocalDateTime.now());
        sysZone.setName(createSysZoneInitCommand.getZoneName());
        sysZone.setId(zoneCode);
        sysZoneRepository.story(sysZone);
        // 关联区域
        SysZoneUser sysZoneUser = new SysZoneUser();
        sysZoneUser.setUserId(userDetails.getId());
        sysZoneUser.setZoneCode(zoneCode);
        sysZoneUser.setIsDeleted(false);
        sysZoneUser.setCreateTime(LocalDateTime.now());
        sysZoneUserRepository.story(sysZoneUser);
        // 新增区域用户超级管理员
        addAdmin(userDetails.getId(), zoneCode);
        return ResultFactory.successOf();
    }

    /**
     * 添加超级管理员
     */
    public void addAdmin(Long userId, String zoneId) {
        // 创建角色
        SysRole sysRole = new SysRole();
        sysRole.setCode("admin");
        sysRole.setName("超级管理员");
        sysRole.setIsDeleted(false);
        sysRole.setParentCode("0");
        sysRole.setZoneId(zoneId);
        sysRole.setStatus(true);

        sysRoleRepository.story(sysRole);

        Result<SysRole> sysRoleRepositoryOne = sysRoleRepository.findOne(sysRole);
        Long roleId = sysRoleRepositoryOne.getData().getId();

        // 创建角色权限
        SysUserRole sysUserRole = new SysUserRole();
        sysUserRole.setUserId(userId);
        sysUserRole.setRoleId(roleId);
        sysUserRole.setIsDeleted(false);
        sysUserRole.setZoneId(zoneId);


        sysUserRoleRepository.story(sysUserRole);
        // 扫描所有权限然后赋值给角色
        Result<List<SysPermissionDTO>> scanPermission = sysPermissionRepository.findScanPermission();

        if (scanPermission.hasSuccessData()) {
            List<SysRolePermission> rolePermissions =
                    scanPermission
                            .getData()
                            .stream().map(sysPermissionDTO -> {
                                SysRolePermission sysRolePermission = new SysRolePermission();
                                sysRolePermission.setIsDeleted(false);
                                sysRolePermission.setRoleId(roleId);
                                sysRolePermission.setPermissionId(sysPermissionDTO.getUrl() + NormalUsedString.UNDERSCORE + sysPermissionDTO.getMethod());
                                sysRolePermission.setZoneId(zoneId);
                                return sysRolePermission;
                            })
                            .toList();

            sysRolePermissionRepository.batchStory(rolePermissions);

        }
    }

    /**
     * 获取用户权限
     *
     * @param userId 用户ID
     * @return
     */
    @Override
    public Result<List<SysPermission>> findUserPermissionList(Long userId) {
        return sysUserRepository.findUserPermissionList(userId);
    }
}